package com.alogic.es.xscript;

import com.alogic.es.client.IndexerTool;
import com.alogic.es.core.Indexer;
import com.alogic.lucene.core.ExtAnalyzer;
import com.alogic.xscript.ExecuteWatcher;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.alogic.xscript.plugins.Segment;
import com.anysoft.util.IOTools;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;

import java.io.IOException;

/**
 * 分词插件
 *
 * @since 1.6.13.9 [20200824 duanyy]
 */
public class EsSegment extends Segment {
    /**
     * 父节点的上下文id
     */
    protected String pid = "$indexer";

    /**
     * 当不存在父节点时自动连接indexer
     */
    protected String indexerId = "default";

    /**
     * 待分析的文本
     */
    protected String $text = "";

    protected String $field = "default";

    protected String valueId = "$es-value";
    protected String typeId = "$es-type";
    protected String startId = "$es-start";
    protected String endId = "$es-end";
    protected String domainId = "$es-domain";
    protected String tagsId = "$es-tags";
    protected boolean extMode = false;

    public EsSegment(String tag, Logiclet p) {
        super(tag, p);
    }

    @Override
    public void configure(Properties p){
        super.configure(p);

        pid = PropertiesConstants.getString(p,"pid",pid,true);
        indexerId = PropertiesConstants.getString(p,"indexerId",indexerId,true);
        $text = PropertiesConstants.getRaw(p,"text",$text);
        $field = PropertiesConstants.getRaw(p,"field",$field);

        valueId = PropertiesConstants.getString(p,"valueId",valueId,true);
        typeId = PropertiesConstants.getString(p,"typeId",typeId,true);
        startId = PropertiesConstants.getString(p,"startId",startId,true);
        endId = PropertiesConstants.getString(p,"endId",endId,true);
        domainId = PropertiesConstants.getString(p,"domainId",domainId,true);
        tagsId = PropertiesConstants.getString(p,"tagsId",tagsId,true);
        extMode = PropertiesConstants.getBoolean(p,"extMode",extMode,true);
    }

    @Override
    protected void onExecute(XsObject root, XsObject current, LogicletContext ctx, ExecuteWatcher watcher) {
        Indexer indexer = ctx.getObject(pid);
        if (indexer == null){
            if (StringUtils.isNotEmpty(indexerId)){
                indexer = IndexerTool.getIndexer(indexerId);
            }
            if (indexer == null){
                log(String.format("[%s] Indexer is not found,pid = %s",this.getXmlTag(),pid),"warning");
                return;
            }
        }

        String text = PropertiesConstants.transform(ctx, $text, "");

        if (StringUtils.isNotEmpty(text)){
            Analyzer analyzer = indexer.getAnalyzer();
            TokenStream ts = null;
            try {
                ts = analyzer.tokenStream(PropertiesConstants.transform(ctx, $field, "default"), text);

                CharTermAttribute cta = ts.getAttribute(CharTermAttribute.class);
                TypeAttribute ta = ts.getAttribute(TypeAttribute.class);
                OffsetAttribute oa = ts.getAttribute(OffsetAttribute.class);

                ts.reset();
                while (ts.incrementToken()){
                    String word = cta.toString();
                    ctx.SetValue(valueId, word);
                    ctx.SetValue(typeId, ta.type());
                    ctx.SetValue(startId, String.valueOf(oa.startOffset()));
                    ctx.SetValue(endId,String.valueOf(oa.endOffset()));

                    if (extMode && analyzer instanceof ExtAnalyzer){
                        ExtAnalyzer extAnalyzer = (ExtAnalyzer)analyzer;
                        ExtAnalyzer.WordInfo wordInfo = extAnalyzer.getWordInfo(word);
                        ctx.SetValue(domainId,wordInfo == null?"default":wordInfo.getDomain());
                        ctx.SetValue(tagsId,wordInfo == null?word:wordInfo.getTags());
                    }

                    super.onExecute(root, current, ctx, watcher);
                }
            } catch (IOException e) {
                log(String.format("[%s] Failed to analyze text : %s",this.getXmlTag(),text),"error");
            }finally{
                IOTools.close(ts);
            }
        }
    }
}
